package cloud.topdaddy.base.utils;

import jakarta.annotation.PostConstruct;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.lionsoul.ip2region.xdb.Searcher;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.FileCopyUtils;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.TimeUnit;

/**
 * IP地址解析工具类
 * 基于 ip2region 库实现IP地址定位功能
 *
 * @author topdaddy
 * @since 2025-07-01 14:22:43
 */
@Slf4j
public class IpParserUtil {

    /**
     * ip2region.xdb 文件路径
     */
    private static final String IP_DB_PATH = "ip2region.xdb";

    /**
     * 缓存 Searcher 对象
     */
    private static Searcher searcher;

    /**
     * 初始化方法，在Spring Bean创建后执行
     */
    @PostConstruct
    public void init() {
        loadIpDatabase();
    }

    /**
     * 加载IP数据库文件
     */
    private static void loadIpDatabase() {
        try {
            // 从classpath中获取xdb文件
            ClassPathResource classPathResource = new ClassPathResource(IP_DB_PATH);
            InputStream inputStream = classPathResource.getInputStream();

            // 将xdb文件读取为字节数组
            byte[] cBuff = FileCopyUtils.copyToByteArray(inputStream);

            // 创建完全基于内存的查询对象
            searcher = Searcher.newWithBuffer(cBuff);

            log.info("IP数据库加载成功");
        } catch (IOException e) {
            log.error("加载IP数据库文件失败", e);
        }
    }

    /**
     * 解析IP地址，获取地理位置信息
     *
     * @param ip IP地址
     * @return 地理位置信息，格式：国家|区域|省份|城市|ISP
     *         示例：中国|0|广东省|深圳市|电信
     */
    public static String parseIp(String ip) {
        if (searcher == null) {
            log.warn("IP数据库未初始化");
            return null;
        }

        try {
            long startTime = System.nanoTime();
            // 执行查询
            String region = searcher.search(ip);
            long endTime = System.nanoTime();

            // 计算查询耗时
            long cost = TimeUnit.NANOSECONDS.toMicros(endTime - startTime);
            log.debug("IP查询完成: {} => {} 耗时: {}μs", ip, region, cost);

            return region;
        } catch (Exception e) {
            log.error("解析IP地址失败: {}", ip, e);
            return null;
        }
    }

    /**
     * 解析IP地址并返回详细信息对象
     *
     * @param ip IP地址
     * @return IpInfo对象
     */
    public static IpInfo parseIpInfo(String ip) {
        String region = parseIp(ip);
        if (region == null) {
            return null;
        }

        return new IpInfo(region);
    }

    /**
     * IP信息封装类
     */
    @Setter
    @Getter
    public static class IpInfo {
        // Getters and Setters
        private String country;   // 国家
        private String region;    // 地区
        private String province;  // 省份
        private String city;      // 城市
        private String isp;       // 运营商

        public IpInfo(String region) {
            if (region != null && !region.isEmpty()) {
                String[] parts = region.split("\\|");
                if (parts.length >= 5) {
                    this.country = "0".equals(parts[0]) ? null : parts[0];
                    this.region = "0".equals(parts[1]) ? null : parts[1];
                    this.province = "0".equals(parts[2]) ? null : parts[2];
                    this.city = "0".equals(parts[3]) ? null : parts[3];
                    this.isp = "0".equals(parts[4]) ? null : parts[4];
                }
            }
        }

        @Override
        public String toString() {
            return String.format("%s|%s|%s|%s|%s",
                    country != null ? country : "未知",
                    region != null ? region : "未知",
                    province != null ? province : "未知",
                    city != null ? city : "未知",
                    isp != null ? isp : "未知");
        }
    }
}
